{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "03f823e3-6d32-4ef6-8558-d34e6c20900d",
   "metadata": {},
   "source": [
    "## Multiple Chain 快速入门\n",
    "\n",
    "Runnables 可以轻松地用来串联多个 Chains，使用 RunnablePassthrough 将输出同时传给多条后继链。\n",
    "\n",
    "```\n",
    "     Input\n",
    "      / \\\n",
    "     /   \\\n",
    " Chain1 Chain2\n",
    "     \\   /\n",
    "      \\ /\n",
    "      Combine\n",
    "```\n",
    "\n",
    "本指南展示如何使用 Runnable 实现多个 AI 关于相同话题的辩论：\n",
    "\n",
    "```\n",
    "    输入话题\n",
    "       |\n",
    "       |\n",
    "    原始观点\n",
    "      / \\\n",
    "     /   \\\n",
    " 正面论述 反面论述\n",
    "     \\   /\n",
    "      \\ /\n",
    "     最终总结\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "3a699e45-c4ea-460a-8dec-1ab973b5daf7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入相关模块，包括运算符、输出解析器、聊天模板、ChatOpenAI 和 运行器\n",
    "from operator import itemgetter\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain_core.runnables import RunnablePassthrough\n",
    "\n",
    "# 创建一个计划器，生成一个关于给定输入的论证\n",
    "planner = (\n",
    "    ChatPromptTemplate.from_template(\"生成关于以下内容的论点: {input}\")\n",
    "    | ChatOpenAI()\n",
    "    | StrOutputParser()\n",
    "    | {\"base_response\": RunnablePassthrough()}\n",
    ")\n",
    "\n",
    "# 创建正面论证的处理链，列出关于基础回应的正面或有利的方面\n",
    "arguments_for = (\n",
    "    ChatPromptTemplate.from_template(\n",
    "        \"列出关于{base_response}的正面或有利的方面\"\n",
    "    )\n",
    "    | ChatOpenAI()\n",
    "    | StrOutputParser()\n",
    ")\n",
    "\n",
    "# 创建反面论证的处理链，列出关于基础回应的反面或不利的方面\n",
    "arguments_against = (\n",
    "    ChatPromptTemplate.from_template(\n",
    "        \"列出关于{base_response}的反面或不利的方面\"\n",
    "    )\n",
    "    | ChatOpenAI()\n",
    "    | StrOutputParser()\n",
    ")\n",
    "\n",
    "# 创建最终响应者，综合原始回应和正反论点生成最终的回应\n",
    "final_responder = (\n",
    "    ChatPromptTemplate.from_messages(\n",
    "        [\n",
    "            (\"ai\", \"{original_response}\"),\n",
    "            (\"human\", \"正面观点:\\n{results_1}\\n\\n反面观点:\\n{results_2}\"),\n",
    "            (\"system\", \"给出批评后生成最终回应\"),\n",
    "        ]\n",
    "    )\n",
    "    | ChatOpenAI()\n",
    "    | StrOutputParser()\n",
    ")\n",
    "\n",
    "# 构建完整的处理链，从生成论点到列出正反论点，再到生成最终回应\n",
    "chain = (\n",
    "    planner\n",
    "    | {\n",
    "        \"results_1\": arguments_for,\n",
    "        \"results_2\": arguments_against,\n",
    "        \"original_response\": itemgetter(\"base_response\"),\n",
    "    }\n",
    "    | final_responder\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "21340302-7a49-48af-a4a5-b516cb5596e0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'在面对房地产低迷的情况下，我们需要综合考虑正面和反面观点，以找到平衡和解决问题的方法。尽管房地产市场低迷可能会带来一些负面影响，但也有一些积极的方面。我们可以通过政府政策的引导和市场自我调整，来应对潜在的风险和挑战。同时，房地产市场的低迷也可能为购房者提供更好的购房机会，促进市场的健康发展。因此，我们应该以开放的心态和理性的态度来看待房地产市场的变化，并寻求合适的解决方案，以实现经济的平稳发展和社会的和谐进步。'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.invoke({\"input\": \"房地产低迷\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a9aabaf-2ce7-4ce2-ad44-f11b0dfe0f4b",
   "metadata": {},
   "source": [
    "#### 流式输出"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "58380571-fa69-426e-95a8-d17ebd61d147",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "尽管国际合作和协调在推动全球经济稳定和可持续发展方面可能会遇到一些困难和挑战，但我们仍然认为国际合作至关重要。通过共同努力克服障碍，各国可以共同应对全球经济面临的挑战，实现共同繁荣和可持续发展。国际合作不仅可以促进经济增长和贸易自由化，还能够解决全球性问题，为全球经济的发展开辟更广阔的前景。因此，我们仍然强调国际合作的重要性，并呼吁各国共同努力，共同应对全球经济挑战。"
     ]
    }
   ],
   "source": [
    "## chain 最终输出经过了 StrOutputParser 处理，所以可以直接输出流式输出 s\n",
    "for s in chain.stream({\"input\": \"全球经济\"}):\n",
    "    print(s, end=\"\", flush=True)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
